#pragma once

#include "logger.hpp"
#include "icsearch.hpp"
#include "user.hxx"
#include "message.hxx"


namespace xu
{
    
    class ESClientFactory
    {
    public:
        static ClientPtr Create(const std::vector<std::string> &host_list)
        {
            return std::make_shared<elasticlient::Client>(host_list);
        }
    };
    const std::string user_id = "user_id";
    const std::string nickname = "nickname";
    const std::string description = "description";
    const std::string phone_number = "phone_number";
    const std::string avatar_id = "avatar_id";
    const std::string index_name = "user_info1";
    const std::string create_id = "0001";

    class ESUser
    {
    public:
        using ptr = std::shared_ptr<ESUser>;
        ESUser(const ClientPtr & client)
        :_client(client)
        {
            if(CreateIndex() == false)
            {
                LOG_ERROR("创建索引失败");
            }
        }

        bool CreateIndex()
        {
            bool ret = ESIndex(_client, index_name)
            .Append(user_id,"keyword","standard",false)
            .Append(nickname,"text", "ik_max_word",false)
            .Append(description)
            .Append(phone_number,"keyword", "standard",false)
            .Append(avatar_id)
            .Create(create_id);
            if(ret == false)
            {
                LOG_INFO("索引创建失败!");
                return false;
            }

            LOG_INFO("索引创建成功!");
            return true;
        }

        bool Insert(User & user)
        {
            bool ret = xu::ESInsert(_client, index_name)
            .Append(user_id, user.user_id())
            .Append(nickname, user.nickname())
            .Append(description, user.description())
            .Append(phone_number, user.phone_number())
            .Append(avatar_id, user.avatar_id())
            .Insert(user.user_id());
            if (ret == false) 
            {
                LOG_ERROR("数据插入/更新失败!");
                return false;
            }

            LOG_INFO("数据新增/更新成功!");
            return true;
        }
        
        std::vector<User> Search(const std::string & key,const std::vector<std::string> & must_not)
        {
            std::vector<User> res; 
            std::string user_id_key = user_id + ".keyword";
            Json::Value json_user = xu::ESSearch(_client, index_name)
            .AppendShould(phone_number+".keyword",key)
            .AppendShould(user_id_key,key)
            .AppendShould(nickname+".keyword",key)
            .AppendMustNot(user_id_key, must_not)
            .Search();
            if (json_user.empty() || json_user.isArray() == false) 
            {
                LOG_ERROR("结果为空，或者结果不是数组类型");
                return res;
            } 
            int sz = json_user.size();
            for (int i = 0; i < sz; i++) {
                User user;
                user.user_id(json_user[i]["_source"][user_id].asString());
                user.nickname(json_user[i]["_source"][nickname].asString());
                user.description(json_user[i]["_source"][description].asString());
                user.phone_number(json_user[i]["_source"][phone_number].asString());
                user.avatar_id(json_user[i]["_source"][avatar_id].asString());
                res.push_back(user);
            }
            LOG_INFO("数据检索成功!");
            return res;
        }

    private:
        ClientPtr _client;
    };

    class ESMessage
    {
    public:
        using ptr = std::shared_ptr<ESMessage>;
        ESMessage(const ClientPtr & client)
        :_client(client)
        {
            if(CreateIndex() == false)
            {
                LOG_ERROR("创建索引失败");
            }
        }

        bool CreateIndex()
        {
            bool ret = ESIndex(_client, "message")
            .Append("user_id", "keyword", "standard", false)
            .Append("message_id", "keyword", "standard", false)
            .Append("create_time", "long", "standard", false)
            .Append("chat_session_id", "keyword", "standard", true)
            .Append("content")
            .Create("0002");

            if (ret == false) {
                LOG_INFO("消息信息索引创建失败!");
                return false;
            }
            LOG_INFO("消息信息索引创建成功!");
            return true;
        }

        bool Insert(const std::string &user_id,
                const std::string &message_id,
                const long create_time,
                const std::string &chat_session_id,
                const std::string &content) 
        {
                bool ret = ESInsert(_client, "message")
                    .Append("message_id", message_id)
                    .Append("create_time", create_time)
                    .Append("user_id", user_id)
                    .Append("chat_session_id", chat_session_id)
                    .Append("content", content)
                    .Insert(message_id);
                if (ret == false) {
                    LOG_ERROR("消息数据插入/更新失败!");
                    return false;
                }
                LOG_INFO("消息数据新增/更新成功!");
                return true;
        }


        bool Remove(const std::string &mid) 
        {
                bool ret = ESRemove(_client, "message").Remove(mid);
                if (ret == false) {
                    LOG_ERROR("消息数据删除失败!");
                    return false;
                }
                LOG_INFO("消息数据删除成功!");
                return true;
        }

        std::vector<xu::Message> Search(const std::string &key, const std::string &ssid) 
        {
                std::vector<xu::Message> res;
                Json::Value json_user = ESSearch(_client, "message")
                    .AppendMustTerm("chat_session_id.keyword", ssid)
                    .AppendMustMatch("content", key)
                    .Search();
                if (json_user.isArray() == false) {
                    LOG_ERROR("用户搜索结果为空，或者结果不是数组类型");
                    return res;
                }
                int sz = json_user.size();
                LOG_DEBUG("检索结果条目数量：{}", sz);
                for (int i = 0; i < sz; i++) {
                    xu::Message message;
                    message.from_user_id(json_user[i]["_source"]["user_id"].asString());
                    message.message_id(json_user[i]["_source"]["message_id"].asString());
                    boost::posix_time::ptime ctime(boost::posix_time::from_time_t(
                        json_user[i]["_source"]["create_time"].asInt64()));
                    message.created_time(ctime);
                    message.to_session_id(json_user[i]["_source"]["chat_session_id"].asString());
                    message.content(json_user[i]["_source"]["content"].asString());
                    res.push_back(message);
                }
                return res;
        }

    private:
        ClientPtr _client;
    };

}